let Vue;
function forEach(obj, callback) {
  Object.keys(obj).forEach(key => {
    callback(key, obj[key]);
  });
}
class Store {
  constructor(options) {
    this.options = options;
    this.initState();
    this.initGetters();
    this.initMutations();
    this.initActions();
    // 102分 modules
  }

  initState() {
    // this._s = this.options.state;
    this._s = new Vue({
      data: {
        state: this.options.state
      }
    });
  }

  initGetters() {
    const getters = this.options.getters || {};
    this.getters = {};
    forEach(getters, (key, value) => {
      // this.getters[key] = getters[key](this.state);  无法响应式
      Object.defineProperty(this.getters, key, {
        get: () => {
          return value(this.state);
        }
      });
    });
  }

  initMutations() {
    const mutations = this.options.mutations || {};
    this.mutations = {};
    forEach(mutations, (key, value) => {
      this.mutations[key] = (payload) => {
        value.call(this, this.state, payload);
      }
    });
  }

  initActions() {
    const actions = this.options.actions || {};
    this.actions = {};
    forEach(actions, (key, value) => {
      this.actions[key] = (payload) => {
        value.call(this, this, payload);
      }
    });
  }

  // 用箭头函数保证this指向
  commit = (type, payload) => {
    this.mutations[type](payload);
  }

  dispatch = (type, payload) => {
    this.actions[type](payload);
  }

  get state() {
    return this._s.state;
  }
}
const instance = {
  install(_Vue, options) {
    console.log('install');
    Vue = _Vue;

    // 给每个Vue实例都挂在同一个new Vuex.Store实例
    Vue.mixin({
      beforeCreate() {
        console.log('before');
        /*
        * 判断是子组件还是父组件，如果是子组件，需要获取到父组件的store属性(main.js)
        * */
        if (this.$options && this.$options.store) { // main.js
          this.$store = this.$options.store;
        } else {  // 子组件
          this.$store = this.$parent && this.$parent.$store;
        }
      }
    });
  },
  Store
};

export default instance;